home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
ka9q_src.arc
/
NR3.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-28
|
22KB
|
838 lines
/* cat > ./nr3.c << '\Rogue\Monster\' */
/* net/rom level 3 low level processing */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#include "timer.h"
#include "arp.h"
#include "slip.h"
#include "ax25.h"
#include "netrom.h"
#include "lapb.h"
#include <ctype.h>
/* Nodes message broadcast address: "NODES" in shifted ASCII */
struct ax25_addr nr_nodebc = {
'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
('0'<<1) | E
} ;
struct nriface nrifaces[NRNUMIFACE] ;
unsigned nr_numiface ;
struct nrnbr_tab *nrnbr_tab[NRNUMCHAINS] ;
struct nrroute_tab *nrroute_tab[NRNUMCHAINS] ;
struct nrnf_tab *nrnf_tab[NRNUMCHAINS] ;
unsigned nr_nfmode = NRNF_NOFILTER ;
unsigned nr_ttl = 64 ;
unsigned obso_init = 6 ;
unsigned obso_minbc = 5 ;
unsigned nr_maxroutes = 5 ;
unsigned nr_autofloor = 1 ;
struct interface *nr_interface ;
/* send IP datagrams across a net/rom network connection */
int
nr_send(bp,interface,gateway,precedence,delay,throughput,reliability)
struct mbuf *bp ;
struct interface *interface ;
int32 gateway ;
char precedence ;
char delay ;
char throughput ;
char reliability ;
{
struct ax25_addr dest ;
struct mbuf *tbp, *htonnr3() ;
struct nr3hdr n3hdr ;
char *hwaddr ;
struct arp_tab *arp ;
if ((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP) {
free_p(bp) ; /* drop the packet if no route */
return ;
}
hwaddr = arp->hw_addr ; /* points to destination */
memcpy(dest.call, hwaddr, ALEN) ;
dest.ssid = hwaddr[ALEN] ;
/* set up host format header */
/* The null source call is a signal to nr_route to insert the call */
/* of the outbound interface. We can't do it here because */
/* we don't know the interface it's going to go out, and */
/* the interfaces might have different callsigns. */
n3hdr.source.call[0] = '\0' ;
n3hdr.dest = dest ;
n3hdr.ttl = nr_ttl ;
/* Convert to a network format header. This will be stripped */
/* back off in nr_route, but them's the breaks. */
if ((tbp = htonnr3(&n3hdr)) == NULLBUF) {
free_p(bp) ;
return ;
}
append(tbp,bp) ; /* append data to header */
nr_route(tbp) ; /* pass off to level 3 routing code */
}
/* Figure out if a call is assigned to one of my net/rom
* interfaces.
*/
static int
ismycall(addr)
struct ax25_addr *addr ;
{
register int i ;
int found = 0 ;
for (i = 0 ; i < nr_numiface ; i++)
if (addreq((struct ax25_addr *)(nrifaces[i].interface->hwaddr),
addr)) {
found = 1 ;
break ;
}
return found ;
}
/* Route net/rom network layer packets.
*/
nr_route(bp)
struct mbuf *bp ;
{
struct nr3hdr n3hdr ;
struct ax25_cb *axp, *find_ax25(), *open_ax25() ;
struct ax25 naxhdr ;
struct ax25_addr neighbor ;
struct mbuf *hbp, *pbp, *htonnr3() ;
extern int16 axwindow ;
void ax_incom() ;
register struct nrnbr_tab *np ;
register struct nrroute_tab *rp ;
register struct nr_bind *bindp, *find_best() ;
struct interface *interface ;
if (ntohnr3(&n3hdr,&bp) == -1) {
free_p(bp) ;
return ;
}
if (ismycall(&n3hdr.dest)) {
ip_route(bp,0) ;
return ;
}
if ((rp = find_nrroute(&n3hdr.dest)) == NULLNRRTAB) {
/* no route, drop the packet */
free_p(bp) ;
return ;
}
if ((bindp = find_best(rp->routes,1)) == NULLNRBIND) {
/* This shouldn't happen yet, but might if we add */
/* dead route detection */
free_p(bp) ;
return ;
}
np = bindp->via ;
memcpy(neighbor.call,np->call,ALEN) ;
neighbor.ssid = np->call[ALEN] ;
interface = nrifaces[np->interface].interface ;
/* Now check to see if the source call is null. That is */
/* a signal from nr_send that the packet originates here, */
/* so we need to insert the callsign of the appropriate */
/* interface */
if (n3hdr.source.call[0] == '\0')
memcpy(&n3hdr.source,interface->hwaddr,AXALEN) ;
/* Make sure there is a connection to the neighbor */
if ((axp = find_ax25(&neighbor)) == NULLAX25 || axp->state != CONNECTED) {
/* Open a new connection or reinitialize old one */
/* hwaddr has been advanced to point to neighbor + digis */
atohax25(&naxhdr, np->call, (struct ax25_addr *)interface->hwaddr) ;
axp = open_ax25(&naxhdr, axwindow, ax_incom, NULLVFP, NULLVFP,
interface,(char *)0) ;
if (axp == NULLAX25) {
free_p(bp) ;
return ;
}
}
if (--n3hdr.ttl == 0) { /* the packet's time to live is over! */
free_p(bp) ;
return ;
}
/* allocate and fill PID mbuf */
if ((pbp = alloc_mbuf(1)) == NULLBUF) {
free_p(bp) ;
return ;
}
pbp->cnt = 1 ;
*pbp->data = (PID_FIRST | PID_LAST | PID_NETROM) ;
/* now format network header */
if ((hbp = htonnr3(&n3hdr)) == NULLBUF) {
free_p(pbp) ;
free_p(bp) ;
return ;
}
append(pbp,hbp) ; /* append header to pid */
append(pbp,bp) ; /* append data to header */
send_ax25(axp,pbp) ; /* pass it off to ax25 code */
}
/* Perform a nodes broadcast on interface # ifno in the net/rom
* interface table.
*/
nr_bcnodes(ifno)
unsigned ifno ;
{
struct mbuf *hbp, *dbp, *savehdr ;
struct nrroute_tab *rp ;
struct nrnbr_tab *np ;
struct nr_bind * bp ;
struct nr3dest nrdest ;
int i, didsend = 0, numdest = 0 ;
register char *cp ;
struct interface *axif = nrifaces[ifno].interface ;
/* prepare the header */
if ((hbp = alloc_mbuf(NR3NODEHL)) == NULLBUF)
return ;
hbp->cnt = NR3NODEHL ;
*hbp->data = NR3NODESIG ;
memcpy(hbp->data+1,nrifaces[ifno].alias,ALEN) ;
/* make a copy of the header in case we need to send more than */
/* one packet */
savehdr = copy_p(hbp,NR3NODEHL) ;
/* now scan through the routing table, finding the best routes */
/* and their neighbors. create destination subpackets and append */
/* them to the header */
for (i = 0 ; i < NRNUMCHAINS ; i++) {
for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
/* look for best, non-obsolescent route */
if ((bp = find_best(rp->routes,0)) == NULLNRBIND)
continue ; /* no non-obsolescent routes found */
if (bp->quality == 0) /* this is a loopback route */
continue ; /* we never broadcast these */
np = bp->via ;
/* insert best neighbor */
memcpy(nrdest.neighbor.call,np->call,ALEN) ;
nrdest.neighbor.ssid = np->call[ALEN] ;
/* insert destination from route table */
nrdest.dest = rp->call ;
/* insert alias from route table */
strcpy(nrdest.alias,rp->alias) ;
/* insert quality from binding */
nrdest.quality = bp->quality ;
/* create a network format destination subpacket */
if ((dbp = htonnrdest(&nrdest)) == NULLBUF) {
free_p(hbp) ; /* drop the whole idea ... */
free_p(savehdr) ;
return ;
}
append(hbp,dbp) ; /* append to header and others */
/* see if we have appended as many destinations */
/* as we can fit into a single broadcast. If we */
/* have, go ahead and send them out. */
if (++numdest == NRDESTPERPACK) { /* filled it up */
didsend = 1 ; /* indicate that we did broadcast */
numdest = 0 ; /* reset the destination counter */
(*axif->output)(axif, (char *)&nr_nodebc, axif->hwaddr,
(PID_FIRST | PID_LAST | PID_NETROM),
hbp) ; /* send it */
hbp = copy_p(savehdr,NR3NODEHL) ; /* new header */
}
}
}
/* Now, here is something totally weird. If our interfaces */
/* have different callsigns than this one, advertise a very */
/* high quality route to them. Is this a good idea? I don't */
/* know. However, it allows us to simulate a bunch of net/roms */
/* hooked together with a diode matrix coupler. */
for (i = 0 ; i < nr_numiface ; i++) {
if (i == ifno)
continue ; /* don't bother with ours */
cp = nrifaces[i].interface->hwaddr ;
if (!addreq((struct ax25_addr *)axif->hwaddr,cp)) {
/* both destination and neighbor address */
memcpy(&nrdest.dest,cp,AXALEN) ;
memcpy(&nrdest.neighbor,cp,AXALEN) ;
/* alias of the interface */
strcpy(nrdest.alias,nrifaces[i].alias) ;
/* and the very highest quality */
nrdest.quality = 255 ;
/* create a network format destination subpacket */
if ((dbp = htonnrdest(&nrdest)) == NULLBUF) {
free_p(hbp) ; /* drop the whole idea ... */
free_p(savehdr) ;
return ;
}
append(hbp,dbp) ; /* append to header and others */
if (++numdest == NRDESTPERPACK) { /* filled it up */